<template>
  <view class="container">
    <view class="game-container">
      <!-- 游戏标题和分数 -->
      <view class="game-info">
        <h1>贪吃蛇游戏</h1>
        <p>分数: {{ score }}</p>
        <p>最高分: {{ highScore }}</p>
      </view>

      <!-- 游戏区域（鼠标点击控制） -->
      <view class="game-board" :style="{ width: boardWidth + 'px', height: boardHeight + 'px' }"
        @click="handleMouseClick" @touchstart="handleTouchStart" @touchend="handleTouchEnd">
        <!-- 蛇身 -->
        <view v-for="(segment, index) in snake" :key="index" class="snake-segment" :style="{ 
            left: segment.x * cellSize + 'px', 
            top: segment.y * cellSize + 'px',
            width: cellSize + 'px',
            height: cellSize + 'px',
            backgroundColor: index === 0 ? 'darkgreen' : 'green'
          }"></view>

        <!-- 食物（带特效） -->
        <view class="food food-blink" :style="{ 
            left: food.x * cellSize + 'px', 
            top: food.y * cellSize + 'px',
            width: cellSize + 'px',
            height: cellSize + 'px',
            backgroundColor: food.color,
            borderRadius: food.shape === 'circle' ? '50%' : food.shape === 'square' ? '3rpx' : '0',
            clipPath: food.shape === 'star' ? 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)' : 'none'
          }"></view>
      </view>

      <!-- 控制按钮 -->
      <view class="controls">
        <button @click="startGame" v-if="!isPlaying">开始游戏</button>
        <button @click="pauseGame" v-if="isPlaying && !isPaused">暂停</button>
        <button @click="resumeGame" v-if="isPaused">继续</button>
        <button @click="resetGame" style="margin-top: 15rpx;">重置游戏</button>
      </view>

      <!-- 游戏结束弹窗 -->
      <view class="game-message" v-if="gameOver">
        <h2>游戏结束!</h2>
        <p>最终得分: {{ score }}</p>
        <button @click="resetGame">再来一局</button>
      </view>

      <!-- 操作说明 -->
      <view class="instructions">
        <p>操作1: 方向键 / W/A/S/D 控制蛇移动</p>
        <p>操作2: 点击游戏区域，蛇向点击方向移动</p>
        <p>操作3: 空格键暂停/继续</p>
      </view>
    </view>
  </view>
</template>

<script setup>
  import {
    ref,
    onMounted,
    onUnmounted
  } from 'vue';

  // 游戏配置
  const cellSize = 20;
  const rows = 20;
  const cols = 20;

  // 游戏状态
  const snake = ref([{
    x: 10,
    y: 10
  }]);
  const food = ref({
    x: 15,
    y: 10,
    color: '#ff0000',
    shape: 'circle'
  });
  const direction = ref({
    x: 1,
    y: 0
  });
  const nextDirection = ref({
    x: 1,
    y: 0
  });
  const score = ref(0);
  const highScore = ref(0);
  const isPlaying = ref(false);
  const isPaused = ref(false);
  const gameOver = ref(false);
  const gameSpeed = ref(150);
  const gameLoop = ref(null);
  const foodStyleTimer = ref(null);

  // 游戏板尺寸
  const boardWidth = cols * cellSize;
  const boardHeight = rows * cellSize;

  // 食物样式配置
  const colorLibrary = [
    '#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff',
    '#ff6347', '#32cd32', '#1e90ff', '#ffd700', '#ff69b4', '#00ced1'
  ];
  const shapeLibrary = ['circle', 'square', 'star'];

  // 随机切换食物样式
  const randomizeFoodStyle = () => {
    food.value.color = colorLibrary[Math.floor(Math.random() * colorLibrary.length)];
    food.value.shape = shapeLibrary[Math.floor(Math.random() * shapeLibrary.length)];
  };

  // 启动食物样式定时器
  const startFoodStyleTimer = () => {
    if (foodStyleTimer.value) clearInterval(foodStyleTimer.value);
    foodStyleTimer.value = setInterval(() => {
      if (isPlaying.value && !gameOver.value) {
        randomizeFoodStyle();
      }
    }, 1000);
  };

  // 鼠标点击控制逻辑
  const handleMouseClick = (e) => {
    if (!isPlaying.value || gameOver.value || isPaused.value) return;

    const boardDom = e.currentTarget;
    const boardRect = boardDom.getBoundingClientRect();
    const clickXInBoard = e.clientX - boardRect.left;
    const clickYInBoard = e.clientY - boardRect.top;
    const clickGridX = Math.floor(clickXInBoard / cellSize);
    const clickGridY = Math.floor(clickYInBoard / cellSize);
    const snakeHead = snake.value[0];
    const diffX = clickGridX - snakeHead.x;
    const diffY = clickGridY - snakeHead.y;

    if (Math.abs(diffX) > Math.abs(diffY)) {
      if (diffX > 0 && direction.value.x !== -1) {
        nextDirection.value = {
          x: 1,
          y: 0
        };
      } else if (diffX < 0 && direction.value.x !== 1) {
        nextDirection.value = {
          x: -1,
          y: 0
        };
      }
    } else {
      if (diffY > 0 && direction.value.y !== -1) {
        nextDirection.value = {
          x: 0,
          y: 1
        };
      } else if (diffY < 0 && direction.value.y !== 1) {
        nextDirection.value = {
          x: 0,
          y: -1
        };
      }
    }
  };

  // 生成食物
  const generateFood = () => {
    let newFood;
    do {
      newFood = {
        x: Math.floor(Math.random() * cols),
        y: Math.floor(Math.random() * rows),
        color: colorLibrary[Math.floor(Math.random() * colorLibrary.length)],
        shape: shapeLibrary[Math.floor(Math.random() * shapeLibrary.length)]
      };
    } while (snake.value.some(segment => segment.x === newFood.x && segment.y === newFood.y));

    food.value = newFood;
  };

  // 移动蛇
  const moveSnake = () => {
    if (isPaused.value || gameOver.value) return;

    direction.value = {
      ...nextDirection.value
    };
    const head = {
      x: snake.value[0].x + direction.value.x,
      y: snake.value[0].y + direction.value.y
    };

    // 撞墙检测
    if (head.x < 0 || head.x >= cols || head.y < 0 || head.y >= rows) {
      endGame();
      return;
    }

    // 撞自己检测
    if (snake.value.some(segment => segment.x === head.x && segment.y === head.y)) {
      endGame();
      return;
    }

    snake.value.unshift(head);

    // 吃食物检测
    if (head.x === food.value.x && head.y === food.value.y) {
      score.value += 10;
      generateFood();

      // 更新最高分
      if (score.value > highScore.value) {
        highScore.value = score.value;
        uni.setStorageSync('snakeHighScore', highScore.value);
      }

      // 加速
      if (score.value % 50 === 0 && gameSpeed.value > 50) {
        gameSpeed.value -= 10;
        restartGameLoop();
      }
    } else {
      snake.value.pop();
    }
  };

  // 开始游戏
  const startGame = () => {
    if (isPlaying.value) return;

    isPlaying.value = true;
    isPaused.value = false;
    gameOver.value = false;

    startGameLoop();
    startFoodStyleTimer();
  };

  // 暂停游戏
  const pauseGame = () => {
    isPaused.value = true;
    cancelAnimationFrame(gameLoop.value);
    if (foodStyleTimer.value) clearInterval(foodStyleTimer.value);
  };

  // 继续游戏
  const resumeGame = () => {
    isPaused.value = false;
    startGameLoop();
    startFoodStyleTimer();
  };

  // 重置游戏
  const resetGame = () => {
    cancelAnimationFrame(gameLoop.value);
    if (foodStyleTimer.value) clearInterval(foodStyleTimer.value);

    snake.value = [{
      x: 10,
      y: 10
    }];
    direction.value = {
      x: 1,
      y: 0
    };
    nextDirection.value = {
      x: 1,
      y: 0
    };
    score.value = 0;
    gameSpeed.value = 150;
    isPlaying.value = false;
    isPaused.value = false;
    gameOver.value = false;

    generateFood();
  };

  // 结束游戏
  const endGame = () => {
    cancelAnimationFrame(gameLoop.value);
    if (foodStyleTimer.value) clearInterval(foodStyleTimer.value);
    isPlaying.value = false;
    gameOver.value = true;
  };

  // 游戏循环
  let lastTime = 0;
  const gameLoopFunction = (timestamp) => {
    if (!lastTime || timestamp - lastTime > gameSpeed.value) {
      lastTime = timestamp;
      moveSnake();
    }
    gameLoop.value = requestAnimationFrame(gameLoopFunction);
  };

  // 启动游戏循环
  const startGameLoop = () => {
    lastTime = 0;
    gameLoop.value = requestAnimationFrame(gameLoopFunction);
  };

  // 重启游戏循环
  const restartGameLoop = () => {
    if (isPlaying.value && !isPaused.value && !gameOver.value) {
      cancelAnimationFrame(gameLoop.value);
      startGameLoop();
    }
  };

  // 键盘控制
  const handleKeydown = (e) => {
    if (!isPlaying.value || gameOver.value) return;

    switch (e.key) {
      case 'ArrowUp':
      case 'w':
      case 'W':
        if (direction.value.y !== 1) nextDirection.value = {
          x: 0,
          y: -1
        };
        break;
      case 'ArrowDown':
      case 's':
      case 'S':
        if (direction.value.y !== -1) nextDirection.value = {
          x: 0,
          y: 1
        };
        break;
      case 'ArrowLeft':
      case 'a':
      case 'A':
        if (direction.value.x !== 1) nextDirection.value = {
          x: -1,
          y: 0
        };
        break;
      case 'ArrowRight':
      case 'd':
      case 'D':
        if (direction.value.x !== -1) nextDirection.value = {
          x: 1,
          y: 0
        };
        break;
      case ' ':
        isPaused.value ? resumeGame() : pauseGame();
        break;
    }
  };

  // 触摸控制
  let touchStartX = 0;
  let touchStartY = 0;
  const handleTouchStart = (e) => {
    touchStartX = e.touches[0].clientX;
    touchStartY = e.touches[0].clientY;
  };
  const handleTouchEnd = (e) => {
    if (!isPlaying.value || gameOver.value) return;

    const touchEndX = e.changedTouches[0].clientX;
    const touchEndY = e.changedTouches[0].clientY;
    const diffX = touchEndX - touchStartX;
    const diffY = touchEndY - touchStartY;

    if (Math.abs(diffX) > Math.abs(diffY)) {
      if (diffX > 0 && direction.value.x !== -1) nextDirection.value = {
        x: 1,
        y: 0
      };
      else if (diffX < 0 && direction.value.x !== 1) nextDirection.value = {
        x: -1,
        y: 0
      };
    } else {
      if (diffY > 0 && direction.value.y !== -1) nextDirection.value = {
        x: 0,
        y: 1
      };
      else if (diffY < 0 && direction.value.y !== 1) nextDirection.value = {
        x: 0,
        y: -1
      };
    }
  };

  // 生命周期
  onMounted(() => {
    const savedHighScore = uni.getStorageSync('snakeHighScore');
    if (savedHighScore) highScore.value = savedHighScore;

    generateFood();
    document.addEventListener('keydown', handleKeydown);
  });

  onUnmounted(() => {
    document.removeEventListener('keydown', handleKeydown);
    cancelAnimationFrame(gameLoop.value);
    if (foodStyleTimer.value) clearInterval(foodStyleTimer.value);
  });
</script>

<style scoped>
  :deep(#app) {
    overflow: hidden;
  }

  .container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: #f0f0f0;
    padding: 20rpx;
    overflow: hidden;
  }

  .game-container {
    text-align: center;
    background-color: white;
    padding: 30rpx;
    border-radius: 10rpx;
    box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
  }

  .game-info {
    margin-bottom: 20rpx;
  }

  .game-info h1 {
    color: #333;
    margin-bottom: 10rpx;
  }

  .game-info p {
    color: #666;
    margin: 5rpx 0;
  }

  .game-board {
    position: relative;
    background-color: #e0e0e0;
    border: 2rpx solid #333;
    margin: 0 auto 20rpx;
    cursor: pointer;
  }

  .snake-segment {
    position: absolute;
    border-radius: 3rpx;
    transition: all 0.1s ease;
  }

  .food {
    position: absolute;
    transition: all 0.3s ease;
  }

  /* 食物闪烁动画 */
  .food-blink {
    animation: blink 1.5s infinite;
  }

  @keyframes blink {

    0%,
    100% {
      opacity: 1;
      transform: scale(1);
    }

    50% {
      opacity: 0.7;
      transform: scale(0.9);
    }
  }

  .controls {
    margin: 20rpx 0;
  }

  .controls button {
    margin: 0 10rpx;
    padding: 10rpx 20rpx;
    background-color: #42b983;
    color: white;
    border: none;
    border-radius: 5rpx;
    cursor: pointer;
    transition: background-color 0.2s;
  }

  .controls button:hover {
    background-color: #359e75;
  }

  .game-message {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(0, 0, 0, 0.8);
    color: white;
    padding: 40rpx;
    border-radius: 10rpx;
    z-index: 100;
  }

  .game-message h2 {
    margin-top: 0;
  }

  .instructions {
    color: #666;
    font-size: 14rpx;
    margin-top: 20rpx;
    line-height: 1.5;
  }
</style>